package user;

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import org.apache.commons.codec.digest.DigestUtils;
import groups.ExerciseGroup;
import hibernate.HibernateUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Session;

/**
 *
 * @author Thorsten Ludwig
 */
@ManagedBean(name="userAdminBean", eager=true)
@ApplicationScoped
public class UserAdminManagedBean {
    /**
     * Look up table for users (by username)
     */
    private UserCollection users;
    
    /**
     * Passwords of the registrated users.
     * The passwords crypted using SHA-512
     */ 
    private PasswordCollection passwords;
    
    public UserAdminManagedBean() {
        this.users = new UserCollection();
        this.passwords = new PasswordCollection();
        this.loadDataFromDB();
        //this.saveValues();
    }
   
    public void createTestData() {
        this.createUsers("Thorsti", "Ludwig", "Thorsten.Ludwig","123","thorsten.ludwig1@gmx.de", "321", "Bachelor","Informatik");
        
        this.createUsers("Julia", "Trieflinger", "Julia", "123", "a@b.de", "12345","Dr.", "Informatik");
        this.createUsers("Peter", "Pan", "Peter.Pan", "12345",  "hiThere", "123", "Bachelor","Physik");
        this.createUsers("Peter", "Lustig", "Peter.Lustig", "54321",  "overHere", "123", "Master", "Mathematik");
        this.createUsers("Peter", "Paul", "Peter.Paul", "1111",  "ack", "123","Diplom", "Bioinformatik");
        this.createUsers("Peter", "derMeter", "Peter.derMeter", "180", "hansi_wansi@gmx.de", "123","Magister", "Kognitionswissenschaft");
        this.createUsers("Peter", "Fox", "Peter.Fox", "666666",  "ludwigt@informatik.uni-tuebingen.de", "123","Master","Medieninformatik");
        
        this.createUsers("Lass miranda", "Densiwilja", "simpson", "admin123","haha@hihi.de","87654321", "Bachelor","Psychologie");
        User u = this.getUser("Julia");
        u.assignRole("Informatik 1 für Informatiker", Role.ADMIN);
    }
    
    /**
     *
     * @param mail
     * @return
     */
    public boolean isMailUsed(String mail) {
        for (User u: this.users.getField().values()){
            if (u.getEmail().equals(mail))
                return true;
        }
        return false;
    }

    /**
     * add a user
     * @param name name of the user
     * @param pw password of the user
     * @param mail mail adress of the user
     * @return true if creation was succesful
     */
    public boolean createUsers(String firstName, 
                                String lastName, 
                                String username, 
                                String pw, 
                                String mail, 
                                String matrikelnummer,
                                String aspiredDegree,
                                String course) {

        if (this.isMailUsed(mail)) {
            return false;
        }
        System.out.println("Erstelle User " + username + " mit Passwort " + pw);
        User newUser = new User(firstName, lastName, username, matrikelnummer, mail,aspiredDegree, course);
        Session session = HibernateUtil.getSession();
        session.beginTransaction();
        
        this.passwords.getField().put(username, this.crypt(pw));
        session.saveOrUpdate(this.passwords);
        this.users.getField().put(username, newUser);
        session.save(newUser);
        session.getTransaction().commit();
        return true;
    }
    
    private String crypt(String pw) {
        return DigestUtils.sha512Hex(pw);
    }

    /**
     * log in the user
     * @param name username
     * @param pw password of the user
     * @return was the login succesful?
     */
    public boolean login(String name, String pw) {
        Boolean result = true;
        try {
            String rightPw = this.passwords.getField().get(name);
            result = rightPw.equals(this.crypt(pw));
        } catch (NullPointerException e) {
            result = false;
        } finally {
            return result;
        }
    }

    /**
     * return user by username
     * @param name name of the user
     * @return User the user
     */
    public User getUser(String name) {
        return this.users.getField().get(name);
    }

    /**
     * assign a user to a specified exercise group
     * @param tutorium the exercise group, where the user become tutor
     * @param user user, who become a tutor
     */
    public void assignUserAsTutor(ExerciseGroup tutorium, User user) {
        tutorium.addLeader(user.getUsername());
    }
    
    public void saveDataToDB() {  
        System.out.println("Öffne Session");
        Session session = HibernateUtil.getSession();
        System.out.println("Beginne Speichern");
        
        session.beginTransaction();
        session.saveOrUpdate(this.passwords);
        session.saveOrUpdate(this.users);
        session.getTransaction().commit();        
        System.out.println("Speichern Abgeschlossen");                
    }

    public void loadDataFromDB() {
        Session session = HibernateUtil.getSession();
        
        session.beginTransaction();
        System.out.println("Beginne laden");
        
        List result = session.createQuery( "from PasswordCollection" ).list();
        for (PasswordCollection pc : (List<PasswordCollection>) result ) {
            Map<String,String> map = new HashMap<String,String>();
            Map<String,String> loadedMap = pc.getField();
            for (String s: loadedMap.keySet()) {
                map.put(s, loadedMap.get(s));
            }
            this.passwords.setField(map);
            System.out.println("Passwörter geladen");
        }
        
        result = session.createQuery( "from UserCollection" ).list();
        for ( UserCollection uc : (List<UserCollection>) result ) {
            Map<String,User> map = new HashMap<String,User>();
            Map<String,User> loadedMap = uc.getField();
            for (String s: loadedMap.keySet()) {
                User u = loadedMap.get(s);
                u.setRights(new HashMap<String,Role>(u.getRights()));
                map.put(s, u);
            }
            this.users.setField(map);
            System.out.println("User geladen");
        }
        
        System.out.println("Laden abgeschlossen");
        session.getTransaction().commit();
        System.out.println("User: Sessin offen" + session.isOpen());
    }
    
    public List<User> getUsers() {
        return new ArrayList<User>(this.users.getField().values());
    }
}
